package edu.vt.ece.rt.dstm;

import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import edu.vt.ece.rt.benchmark.bank.BankAccount;
import edu.vt.ece.rt.util.Logger.Logger;


/**
 * Base Class for any Quorum Object
 * @author Sudhanshu
 */
public abstract class QObject implements Cloneable, Serializable, Comparable{
	AtomicInteger version = new AtomicInteger(0);
	AtomicLong owner = new AtomicLong(0);				//Useful to establish the ownership while trying to unlock
	
	public Long getOwner(){
		return owner.get();
	}
	
	public int getVersion() {
		return version.get();
	}
	
	public void setVersion(int v){
		version = new AtomicInteger(v);
	}
	public int updateVersion(){
		return version.incrementAndGet();
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Object ob) {
		return ((QObject)ob).getVersion() -  this.version.get() ;	//So that in priority queue head node have highest version object
	}
	
	public boolean lockObject(Long txn){
		if(owner.get() == txn){
			return true;		//If already owner
		}
		return owner.compareAndSet(0, txn);
	}
	
	public boolean unlockObject(Long txn){
		Logger.debug(txn + " trying to unlock "+this.getId() +" owned by "+owner);
		return owner.compareAndSet(txn, 0);
	}
	
	public boolean isProtected(Long txn){
		if(owner.get() == txn){
			return false;		//Go ahead if your owner
		}
		Logger.debug("Txn "+txn+" is not owner, Owner is "+owner.get());
		return !(owner.get() == 0);
	}
	/**
	 * Creates a copy of given object, Deep copy should 
	 * be ensure by user, need for Data.copy( )
	 * @return QObject 
	 */
	public abstract QObject clone();

	public abstract String getId();
	
	public static void main(String[] args) {
		BankAccount b = new BankAccount();
		Long txn = new Long(10);
		b.lockObject(txn);
		b.unlockObject(txn);
		System.out.println(b.isProtected(txn));		
	}
}
